from string import Template

from django.utils.translation import gettext_lazy, gettext as _
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from rest_framework.serializers import Serializer
from rest_framework.response import Response
from drf_yasg.utils import swagger_auto_schema, no_body
from drf_yasg import openapi

from core import errors
from utils.iprestrict import IPRestrictor
from apps.api.viewsets import NormalGenericViewSet
from apps.app_users.email_sender import EmailSender
from apps.app_auth_provider.managers import ExternalUserManager
from apps.app_auth_provider.models import EmailVerificationCode


class EmailVerificationCodeViewSet(NormalGenericViewSet):
    permission_classes = []
    pagination_class = None
    lookup_field = 'id'

    @swagger_auto_schema(
        tags=['auth_provider'],
        operation_summary=gettext_lazy('发送邮箱验证码'),
        request_body=no_body,
        manual_parameters=[
            openapi.Parameter(
                name='email',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=True,
                description=gettext_lazy('邮箱')
            ),
            openapi.Parameter(
                name='external_user_id',
                in_=openapi.IN_PATH,
                type=openapi.TYPE_STRING,
                required=True,
                description=gettext_lazy('外部用户ID')
            ),
        ],
        responses={
            200: ''''''
        }
    )
    def create(self, request, *args, **kwargs):
        """
        发送邮箱验证码

            http code 200:
            {
                "email":"xx",
                "external_user_id": "xx"
            }

            http code 400、403、409、500:
            {
                "code": "AccessDenied",
                "message": "回调地址没有认证权限，请联系工作人员添加白名单。"
            }

            error code:
                InvalidArgument: 参数有误；
                Conflict: 此认证服务未提供，请选择其他认证方式。
        """
        external_user_id = request.query_params.get('external_user_id', None)
        email = request.query_params.get('email', None)

        if not email:
            return self.exception_response(
                exc=errors.InvalidArgument(message=_('邮箱地址不能为空。')))

        try:
            validate_email(email)
        except ValidationError:
            return self.exception_response(
                exc=errors.InvalidArgument(message=_('邮箱地址无效，请输入一个有效的邮箱地址。')))

        external_user = ExternalUserManager.get_external_user_by_id(external_user_id)
        if external_user is None:
            return self.exception_response(
                exc=errors.InvalidArgument(message=_('外部用户id无效，用户记录不存在。')))

        veri_code = EmailVerificationCode.create_code(external_user=external_user, email=email, expired_minutes=10)

        removte_ip, proxy_ips = IPRestrictor.get_remote_ip(request=request)

        # 发送邮件
        message = Template(_('''
        您好！

        您正在将此邮箱用于绑定账号和完善个人信息，邮箱验证码为：${code}

        该验证码10分钟内有效，请勿泄漏给他人。如果您未进行此操作，请忽略此邮件。
        ''')).substitute(code=veri_code.code)
        email_config = EmailSender.get_default_email_configs()
        email_obj = EmailSender.build_save_email(
            host=email_config.host, sender=email_config.host_user,
            subject=_('【云坤认证服务】邮箱验证'), receivers=[email],
            message=message, html_message='',
            tag=EmailSender.EmailTag.OTHER.value,
            save_db=True, remote_ip=removte_ip, is_feint=False
        )
        conn = EmailSender.get_default_connection(fail_silently=True, email_config=email_config)
        try:
            EmailSender.do_send_email(connection=conn, email=email_obj, save_db=True)
        except Exception as exc:
            return self.exception_response(exc=errors.Error(message=_('邮件发送失败。') + str(exc)))

        return Response(data={'external_user_id': external_user_id, 'email': email})

    def get_serializer_class(self):
        return Serializer
